package org.yelongframework.model.generator.freemarker;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;
import java.util.Objects;

import org.yelongframework.freemarker.EntityMap;
import org.yelongframework.model.generator.AbstractModelGenerator;
import org.yelongframework.model.generator.ModelGenerateException;
import org.yelongframework.model.generator.freemarker.datamodel.ModelGenModelDataModel;
import org.yelongframework.model.generator.freemarker.datamodel.ModelGenModelDataModelBuilder;
import org.yelongframework.model.generator.manager.GenModelAndTable;

import freemarker.template.Template;

/**
 * 抽象实现的模型组件生成器
 * 
 * @since 1.0.0
 */
public abstract class AbstractFreemarkerModelGenerator extends AbstractModelGenerator
		implements FreemarkerModelGenerator {

	/** 模板模型工厂 */
	private final ModelGenModelDataModelBuilder modelGenModelDataModelBuilder;

	// ==================================================构造器==================================================

	/**
	 * @param modelGenModelDataModelBuilder 模板模型工厂
	 */
	public AbstractFreemarkerModelGenerator(ModelGenModelDataModelBuilder modelGenModelDataModelBuilder) {
		this.modelGenModelDataModelBuilder = Objects.requireNonNull(modelGenModelDataModelBuilder,
				"modelGenModelDataModelBuilder");
	}

	// ==================================================生成==================================================

	@Override
	public void generate(GenModelAndTable genModelAndTable, OutputStream outputStream) throws ModelGenerateException {
		try {
			// 拦截器
			genModelAndTable = processInterceptor(genModelAndTable);
			// 数据模型
			ModelGenModelDataModel modelGenModelDataModel = getModelGenModelDataModelBuilder().build(genModelAndTable);
			// 数据模型
			Map<String, Object> dataModel = buildDataModel(modelGenModelDataModel);
			// 模板
			Template template = getTemplate();
			// 生成
			template.process(dataModel, new OutputStreamWriter(outputStream));
		} catch (ModelGenerateException e) {
			throw e;
		} catch (Exception e) {
			throw new ModelGenerateException(e);
		}
	}

	// ==================================================数据模型==================================================

	/**
	 * 构建数据模型
	 * 
	 * @param modelGenModelDataModel 模板模型
	 * @return 数据模型
	 */
	protected Map<String, Object> buildDataModel(ModelGenModelDataModel modelGenModelDataModel) {
		return new EntityMap<>(modelGenModelDataModel);
	}

	// ==================================================模板==================================================

	/**
	 * @return 模板
	 */
	protected abstract Template getTemplate() throws Exception;

	// ==================================================模板模型工厂==================================================

	@Override
	public ModelGenModelDataModelBuilder getModelGenModelDataModelBuilder() {
		return modelGenModelDataModelBuilder;
	}

}
